package com.gitee.wsl.prism4j.languages


import com.gitee.wsl.prism4j.GrammarUtils
import com.gitee.wsl.prism4j.Prism4j
import com.gitee.wsl.prism4j.Prism4j.Companion.grammar
import com.gitee.wsl.prism4j.Prism4j.Companion.pattern
import com.gitee.wsl.prism4j.Prism4j.Companion.token
import com.gitee.wsl.prism4j.Prism4j.Pattern

@Suppress("unused")
//@Aliases("dotnet")
//@Extend("clike")
object Prism_csharp {
    fun create(prism4j: Prism4j): Prism4j.Grammar {
        val classNameInsidePunctuation: Prism4j.Grammar? = grammar(
            "inside",
            token("punctuation", pattern(Pattern.compile("\\.")))
        )

        val csharp: Prism4j.Grammar = GrammarUtils.extend(
            GrammarUtils.require(prism4j, "clike"),
            "csharp",
            token(
                "keyword",
                pattern(Pattern.compile("\\b(?:abstract|add|alias|as|ascending|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|descending|do|double|dynamic|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|from|get|global|goto|group|if|implicit|in|int|interface|internal|into|is|join|let|lock|long|namespace|new|null|object|operator|orderby|out|override|params|partial|private|protected|public|readonly|ref|remove|return|sbyte|sealed|select|set|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|value|var|virtual|void|volatile|where|while|yield)\\b"))
            ),
            token(
                "string",
                pattern(
                    Pattern.compile("@(\"|')(?:\\1\\1|\\\\[\\s\\S]|(?!\\1)[^\\\\])*\\1"),
                    false,
                    true
                ),
                pattern(Pattern.compile("(\"|')(?:\\\\.|(?!\\1)[^\\\\\\r\\n])*?\\1"), false, true)
            ),
            token(
                "class-name",
                pattern(
                    Pattern.compile("\\b[A-Z]\\w*(?:\\.\\w+)*\\b(?=\\s+\\w+)"),
                    false,
                    false,
                    null,
                    classNameInsidePunctuation
                ),
                pattern(
                    Pattern.compile("(\\[)[A-Z]\\w*(?:\\.\\w+)*\\b"),
                    true,
                    false,
                    null,
                    classNameInsidePunctuation
                ),
                pattern(
                    Pattern.compile("(\\b(?:class|interface)\\s+[A-Z]\\w*(?:\\.\\w+)*\\s*:\\s*)[A-Z]\\w*(?:\\.\\w+)*\\b"),
                    true,
                    false,
                    null,
                    classNameInsidePunctuation
                ),
                pattern(
                    Pattern.compile("((?:\\b(?:class|interface|new)\\s+)|(?:catch\\s+\\())[A-Z]\\w*(?:\\.\\w+)*\\b"),
                    true,
                    false,
                    null,
                    classNameInsidePunctuation
                )
            ),
            token(
                "number",
                pattern(
                    Pattern.compile(
                        "\\b0x[\\da-f]+\\b|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)f?",
                        Pattern.CASE_INSENSITIVE
                    )
                )
            )
        )

        GrammarUtils.insertBeforeToken(
            csharp, "class-name",
            token(
                "generic-method", pattern(
                    Pattern.compile("\\w+\\s*<[^>\\r\\n]+?>\\s*(?=\\()"),
                    false,
                    false,
                    null,
                    grammar(
                        "inside",
                        token("function", pattern(Pattern.compile("^\\w+"))),
                        token(
                            "class-name",
                            pattern(
                                Pattern.compile("\\b[A-Z]\\w*(?:\\.\\w+)*\\b"),
                                false,
                                false,
                                null,
                                classNameInsidePunctuation
                            )
                        ),
                        GrammarUtils.findToken(csharp, "keyword"),
                        token("punctuation", pattern(Pattern.compile("[<>(),.:]")))
                    )
                )
            ),
            token(
                "preprocessor", pattern(
                    Pattern.compile("(^\\s*)#.*", Pattern.MULTILINE),
                    true,
                    false,
                    "property",
                    grammar(
                        "inside",
                        token(
                            "directive", pattern(
                                Pattern.compile("(\\s*#)\\b(?:define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\\b"),
                                true,
                                false,
                                "keyword"
                            )
                        )
                    )
                )
            )
        )

        return csharp
    }
}
